package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	userv1 "github.com/devops-smartbot/devops-smartbot/proto/gen/go/user/v1"
	"github.com/devops-smartbot/devops-smartbot/services/user-service/internal/auth"
	grpcserver "github.com/devops-smartbot/devops-smartbot/services/user-service/internal/grpc"
	"github.com/devops-smartbot/devops-smartbot/services/user-service/internal/repository"
	"github.com/devops-smartbot/devops-smartbot/services/user-service/internal/service"
	"github.com/devops-smartbot/devops-smartbot/shared/database"
	"google.golang.org/grpc"
	"google.golang.org/grpc/health"
	"google.golang.org/grpc/health/grpc_health_v1"
	"google.golang.org/grpc/reflection"
)

func main() {
	// Get configuration from environment
	port := getEnv("GRPC_PORT", "50055")
	mongoURI := getEnv("MONGO_URI", "mongodb://localhost:27017")
	dbName := getEnv("MONGO_DB_NAME", "devops_smartbot")
	jwtSecret := getEnv("JWT_SECRET", "devops-smartbot-secret-key-change-in-production")

	// JWT expiry times
	accessTokenExpiry := 1 * time.Hour
	refreshTokenExpiry := 7 * 24 * time.Hour

	// Connect to MongoDB
	log.Println("Connecting to MongoDB...")
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()

	db, err := database.Connect(ctx, mongoURI, dbName)
	if err != nil {
		log.Fatalf("Failed to connect to MongoDB: %v", err)
	}
	log.Println("Connected to MongoDB")

	// Initialize repository
	userRepo := repository.NewUserRepository(db)

	// Create indexes
	log.Println("Creating database indexes...")
	if err := userRepo.CreateIndexes(context.Background()); err != nil {
		log.Printf("Warning: Failed to create indexes: %v", err)
	}

	// Initialize JWT manager
	jwtManager := auth.NewJWTManager(jwtSecret, accessTokenExpiry, refreshTokenExpiry)

	// Initialize service
	userService := service.NewUserService(userRepo, jwtManager)

	// Create gRPC server
	grpcServer := grpc.NewServer()

	// Register user service
	server := grpcserver.NewServer(userService)
	userv1.RegisterUserServiceServer(grpcServer, server)

	// Register health check
	healthServer := health.NewServer()
	grpc_health_v1.RegisterHealthServer(grpcServer, healthServer)
	healthServer.SetServingStatus("", grpc_health_v1.HealthCheckResponse_SERVING)

	// Register reflection for grpcurl
	reflection.Register(grpcServer)

	// Start gRPC server
	listener, err := net.Listen("tcp", fmt.Sprintf(":%s", port))
	if err != nil {
		log.Fatalf("Failed to listen: %v", err)
	}

	log.Printf("User Service listening on port %s", port)

	// Handle graceful shutdown
	go func() {
		if err := grpcServer.Serve(listener); err != nil {
			log.Fatalf("Failed to serve: %v", err)
		}
	}()

	// Wait for interrupt signal
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	log.Println("Shutting down user service...")
	grpcServer.GracefulStop()
	log.Println("User service stopped")
}

func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}
